package com.zmn.oms.api.controller.open;

import com.google.common.collect.Maps;
import com.zmn.base.channel.dubbo.interfaces.channel.ChannelListRemoteService;
import com.zmn.common.constant.StatusConsts;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.request.RequestUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.utils.SignUtil;
import com.zmn.oms.model.dto.open.v2.OpenApiV2Request;
import com.zmn.oms.model.dto.order.open.RequestDTO;
import com.zmn.oms.model.entity.chan.plat.ChannelInterface;
import com.zmn.oms.model.entity.dict.ChannelEntrustInterface;
import com.zmn.oms.services.interfaces.dict.ChannelEntrustInterfaceService;
import com.zmn.oms.zmn.business.interfaces.chan.ChannelInterfaceBService;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * 类描述：旧平台订单接口代理
 *
 * @author liuying
 * @date 2019/02/16 17:35
 */
public abstract class OrderBaseController {

    private static final String TEST_SIGN = "TEST_SIGN_ZMN_666888";
    Logger logger = LoggerFactory.getLogger(this.getClass());
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private ChannelListRemoteService channelListRemoteService;
    @Resource
    private ChannelEntrustInterfaceService channelEntrustInterfaceService;
    @Autowired
    private ChannelInterfaceBService channelInterfaceBService;

    /**
     * 数据校验
     *
     * @param requestDTO
     */
    ChannelInterface validateData(HttpServletRequest request, RequestDTO requestDTO, boolean isValIp) throws OmsBaseException {

        if (StringUtils.isBlank(requestDTO.getAppId())) {
            throw new OmsBaseException(StatusConsts.ERROR_PARAMS, "appId不能为空");
        }

        if (StringUtils.isBlank(requestDTO.getSign())) {
            throw new OmsBaseException(StatusConsts.ERROR_PARAMS, "sign不能为空");
        }

        if (requestDTO.getTimestamp() == null) {
            throw new OmsBaseException(StatusConsts.ERROR_PARAMS, "timestamp不能为空");
        }

        // 误差在 10 分钟以内
        long diff = Math.abs(DateUtil.getNowTimestamp() - requestDTO.getTimestamp());
        int maxDiff = 600;
        if (diff > maxDiff && !TEST_SIGN.equals(requestDTO.getSign())) {
            throw new OmsBaseException(StatusConsts.ERROR_PARAMS, "timestamp超出误差范围");
        }

        if (StringUtils.isBlank(requestDTO.getJsonData())) {
            throw new OmsBaseException(StatusConsts.ERROR_PARAMS, "jsonData不能为空");
        }

        // 获取渠道参数
        Optional<ChannelInterface> optional = channelInterfaceBService.findByChannelId(
                Integer.parseInt(requestDTO.getAppId())
        );
        if (!optional.isPresent()) {
            throw new OmsBaseException(StatusConsts.ERROR_ILLEGAL, "appId不存在");
        }

        ChannelInterface channelInterface = optional.get();
        if (!Objects.equals(GlobalConsts.YES, channelInterface.getStatus())) {
            throw new OmsBaseException("appId已停用");
        }

        // 测试签名
        if (TEST_SIGN.equals(requestDTO.getSign())) {
            return channelInterface;
        }

        // 验证签名
        // 1、验证ip
        String ipWhitelist = channelInterface.getIpWhitelist();
        String requestIp = RequestUtil.getRequestIp(request);
        if (isValIp && StringUtils.isNotBlank(ipWhitelist)) {
            if (!ipWhitelist.contains(requestIp)) {
                throw new OmsBaseException(StatusConsts.ERROR_ILLEGAL, "IP限制，非法访问！");
            }
        }

        // 2、获取签名
        Map<String, String> params = Maps.newHashMap();
        Map<String, String[]> map = request.getParameterMap();
        for (String key : map.keySet()) {
            if ("sign".equals(key)) {
                continue;
            }
            if (map.get(key).length > 0) {
                params.put(key, map.get(key)[0]);
            } else {
                params.put(key, "");
            }
        }

        //数据校验
        String sign = SignUtil.signMd5(params, channelInterface.getAppSecret());

        logger.info("interface#request#sign#{}-{}", sign, requestDTO.getSign());

        if (!sign.equals(requestDTO.getSign().toLowerCase())) {
            throw new OmsBaseException(StatusConsts.ERROR_ILLEGAL, "签名错误！");
        }

        return channelInterface;
    }

    /**
     * 数据校验
     *
     * @param v2Request
     */
    ChannelEntrustInterface validateEntrustData(HttpServletRequest request, OpenApiV2Request v2Request, boolean isValIp)
            throws OmsBaseException {

        if (StringUtils.isBlank(v2Request.getAppId())) {
            throw new OmsBaseException(StatusConsts.ERROR_PARAMS, "appId不能为空");
        }

        if (StringUtils.isBlank(v2Request.getSign())) {
            throw new OmsBaseException(StatusConsts.ERROR_PARAMS, "sign不能为空");
        }

        if (v2Request.getTimestamp() == null) {
            throw new OmsBaseException(StatusConsts.ERROR_PARAMS, "timestamp不能为空");
        }

        // 误差在 10 分钟以内
        String timestamp = v2Request.getTimestamp();
        Long timestamp4Long = null;
        try {
            timestamp4Long = Long.parseLong(timestamp);
        } catch (Exception e) {
            throw new OmsBaseException(StatusConsts.ERROR_PARAMS, "timestamp格式错误");
        }

        long diff = Math.abs(DateUtil.getNowTimestamp() - timestamp4Long);
        int maxDiff = 600;
        if (diff > maxDiff && !TEST_SIGN.equals(v2Request.getSign())) {
            throw new OmsBaseException(StatusConsts.ERROR_PARAMS, "timestamp超出误差范围");
        }

        if (StringUtils.isBlank(v2Request.getJsonData())) {
            throw new OmsBaseException(StatusConsts.ERROR_PARAMS, "jsonData不能为空");
        }

        // 获取渠道参数
        Integer channelId = null;
        try {
            channelId = Integer.parseInt(v2Request.getAppId());
        } catch (NumberFormatException e) {
            throw new OmsBaseException(StatusConsts.ERROR_PARAMS, "appId格式错误");
        }
        ChannelEntrustInterface channel = channelEntrustInterfaceService.findByChannelId(channelId);
        if (channel == null) {
            throw new OmsBaseException(StatusConsts.ERROR_ILLEGAL, "appId不存在");
        }

        if (channel.getStatus() != null && !Objects.equals(GlobalConsts.YES, channel.getStatus())) {
            throw new OmsBaseException("appId已停用");
        }

        // 测试签名
        if (TEST_SIGN.equals(v2Request.getSign())) {
            return channel;
        }

        // 2、获取签名
        Map<String, String> params = Maps.newHashMap();
        Map<String, String[]> map = request.getParameterMap();
        for (String key : map.keySet()) {
            if ("sign".equals(key)) {
                continue;
            }
            if (map.get(key).length > 0) {
                params.put(key, map.get(key)[0]);
            } else {
                params.put(key, "");
            }
        }

        //数据校验
        String sign = SignUtil.signMd5(params, channel.getAppSecret());

        logger.info("interface#request#sign#{}-{}", sign, v2Request.getSign());

        if (!sign.equals(v2Request.getSign().toLowerCase())) {
            throw new OmsBaseException(StatusConsts.ERROR_ILLEGAL, "签名错误！");
        }

        return channel;
    }

}
